package response

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"konglu-pay/global"
	"net/http"
	"strings"
)

type R struct {
	Success    bool   `json:"success"`
	ErrCode    int    `json:"err_code"`
	ErrMessage string `json:"err_message"`
	Data       any    `json:"data,omitempty"`
}

const (
	ErrorCodeSuccess = 0
	ErrorCodeFailed  = 1
)

func (r *R) String() string {
	return fmt.Sprintf("R [isSuccess= %t , errCode= %d , errMessage= %s]",
		r.Success,
		r.ErrCode,
		r.ErrMessage,
	)
}

func Result(success bool, errCode int, errMessage string, data any, c *gin.Context) {
	c.JSON(http.StatusOK, R{
		Success:    success,
		ErrCode:    errCode,
		ErrMessage: errMessage,
		Data:       data,
	})
	c.Abort()
}

func Ok(c *gin.Context) {
	Result(true, ErrorCodeSuccess, "ok", nil, c)
}

func OkWithData(c *gin.Context, data any) {
	Result(true, ErrorCodeSuccess, "ok", data, c)
}

func Fail(c *gin.Context) {
	Result(false, ErrorCodeFailed, "fail", nil, c)
}

func FailWithMsg(c *gin.Context, msg string) {
	Result(false, ErrorCodeFailed, msg, nil, c)
}

func FailWithError(c *gin.Context, err error) {
	Result(false, ErrorCodeFailed, err.Error(), nil, c)
}

func FailWithCodeError(c *gin.Context, errCode int, err error) {
	Result(false, errCode, err.Error(), nil, c)
}

func FailWithValidateError(c *gin.Context, err error) {
	errs, ok := err.(validator.ValidationErrors)
	if !ok {
		Result(false, ErrorCodeFailed, "请求参数缺失", nil, c)
	} else {
		Result(false, ErrorCodeFailed, fmt.Sprintf("参数错误:%s", removeTopStructWithOne(errs.Translate(global.ValidateTranslator))), nil, c)
	}
}

func FailWithValidateErrorWithReq(c *gin.Context, req any, err error) {
	reqJson, _ := json.Marshal(&req)
	global.Log.Infof("validate error request: %s %s, req: %s", c.Request.Method, c.FullPath(), reqJson)
	errs, ok := err.(validator.ValidationErrors)
	if !ok {
		Result(false, ErrorCodeFailed, "请求参数缺失", nil, c)
	} else {
		Result(false, ErrorCodeFailed, fmt.Sprintf("参数错误:%s", removeTopStructWithOne(errs.Translate(global.ValidateTranslator))), nil, c)
	}
}

func removeTopStruct(fields map[string]string) map[string]string {
	rsp := map[string]string{}
	for k, v := range fields {
		rsp[k[strings.Index(k, ".")+1:]] = v
	}
	return rsp
}

func removeTopStructWithOne(fields map[string]string) string {
	fieldMap := removeTopStruct(fields)
	for _, v := range fieldMap {
		return v
	}
	return "未知错误"
}

func OkWithStringSuccess(c *gin.Context) {
	c.String(http.StatusOK, "success")
	c.Abort()
}
func FailWithStringFailure(c *gin.Context) {
	c.Status(http.StatusInternalServerError)
	c.Abort()
}
